namespace GemBox.Spreadsheet
{
    using System;
    using System.Drawing;

    public sealed class ExcelCell : AbstractRange
    {
        private object cellValue;
        private ExcelComment comment;
        private SpreadsheetHyperlink hyperlink;
        private CellStyle style;

        internal ExcelCell(ExcelWorksheet parent) : base(parent)
        {
        }

        internal ExcelCell(ExcelWorksheet parent, ExcelCell sourceCell) : base(parent)
        {
            this.cellValue = sourceCell.ValueInternal;
            this.Style = sourceCell.Style;
        }

        internal void AddToMergedRange(MergedCellRange mergedRange)
        {
            if ((mergedRange.Value == null) && (this.cellValue != null))
            {
                mergedRange.ValueInternal = this.cellValue;
                if ((this.style != null) && !this.style.IsDefault)
                {
                    mergedRange.Style = this.style;
                }
            }
            this.AddToMergedRangeInternal(mergedRange);
        }

        internal void AddToMergedRangeInternal(MergedCellRange mergedRange)
        {
            this.cellValue = mergedRange;
        }

        public static DateTime ConvertExcelNumberToDateTime(double num, bool use1904DateSystem)
        {
            DateTime startDate = ExcelFile.GetStartDate(use1904DateSystem);
            if (double.IsNaN(num) || double.IsInfinity(num))
            {
                return startDate;
            }
            long num2 = (long) num;
            long num3 = (long) Math.Round((double) ((num - num2) * 86400.0));
            try
            {
                return startDate.AddDays((double) (num2 - 2L)).AddSeconds((double) num3);
            }
            catch (Exception)
            {
                return startDate;
            }
        }

        internal void RemoveFromMergedRange()
        {
            MergedCellRange cellValue = this.cellValue as MergedCellRange;
            if (cellValue == null)
            {
                throw new Exception("Internal error: cell is not merged.");
            }
            this.cellValue = cellValue.ValueInternal;
            this.style = cellValue.Style;
        }

        public override void SetBorders(MultipleBorders multipleBorders, Color lineColor, LineStyle lineStyle)
        {
            this.Style.Borders.SetBorders(multipleBorders, lineColor, lineStyle);
        }

        public override ExcelComment Comment
        {
            get
            {
                if (this.comment == null)
                {
                    this.comment = new ExcelComment();
                    base.Parent.Shapes.Add(this.comment);
                }
                return this.comment;
            }
            set
            {
                if (this.comment != null)
                {
                    base.Parent.Shapes.DeleteInternal(this.comment.Shape);
                }
                else
                {
                    this.comment = new ExcelComment();
                }
                if (value != null)
                {
                    base.Parent.Shapes.Add(this.comment, new CommentShape(value.Shape));
                }
                else
                {
                    this.comment = null;
                }
            }
        }

        public override string Formula
        {
            get
            {
                CellFormula valueInternal = this.ValueInternal as CellFormula;
                if (valueInternal != null)
                {
                    return valueInternal.Formula;
                }
                return null;
            }
            set
            {
                if ((value == null) || (value == ""))
                {
                    this.ValueInternal = null;
                }
                else
                {
                    this.ValueInternal = new CellFormula(value, base.Parent);
                }
            }
        }

        internal CellFormula FormulaInternal
        {
            get
            {
                object valueInternal = this.ValueInternal;
                if (valueInternal is CellFormula)
                {
                    return (CellFormula) valueInternal;
                }
                return null;
            }
            set
            {
                if (value != null)
                {
                    this.ValueInternal = value;
                }
                else
                {
                    this.ValueInternal = this.Value;
                }
            }
        }

        internal bool HasComment
        {
            get
            {
                return (this.comment != null);
            }
        }

        public bool HasHyperlink
        {
            get
            {
                return (this.hyperlink != null);
            }
        }

        public SpreadsheetHyperlink Hyperlink
        {
            get
            {
                if (this.hyperlink == null)
                {
                    this.hyperlink = new SpreadsheetHyperlink();
                    base.Parent.Hyperlinks.Add(this.hyperlink);
                }
                return this.hyperlink;
            }
            set
            {
                if (this.hyperlink != null)
                {
                    base.Parent.Hyperlinks.DeleteInternal(this.hyperlink);
                }
                if (value != null)
                {
                    this.hyperlink = new SpreadsheetHyperlink(value);
                    base.Parent.Hyperlinks.Add(this.hyperlink);
                }
                else
                {
                    this.hyperlink = null;
                }
            }
        }

        public override bool IsStyleDefault
        {
            get
            {
                if (this.style != null)
                {
                    return this.style.IsDefault;
                }
                return true;
            }
        }

        public CellRange MergedRange
        {
            get
            {
                if (this.cellValue is MergedCellRange)
                {
                    return (MergedCellRange) this.cellValue;
                }
                return null;
            }
        }

        public override CellStyle Style
        {
            get
            {
                if (this.cellValue is MergedCellRange)
                {
                    return ((MergedCellRange) this.cellValue).Style;
                }
                if (this.style == null)
                {
                    this.style = new CellStyle(base.Parent.ParentExcelFile.CellStyleCache);
                }
                return this.style;
            }
            set
            {
                if (this.cellValue is MergedCellRange)
                {
                    ((MergedCellRange) this.cellValue).Style = value;
                }
                else
                {
                    this.style = new CellStyle(value, base.Parent.ParentExcelFile.CellStyleCache);
                }
            }
        }

        public override object Value
        {
            get
            {
                object valueInternal = this.ValueInternal;
                if (valueInternal is CellFormula)
                {
                    valueInternal = ((CellFormula) valueInternal).Value;
                }
                return valueInternal;
            }
            set
            {
                if (value != null)
                {
                    ExcelFile.ThrowExceptionForUnsupportedType(value.GetType());
                }
                object valueInternal = this.ValueInternal;
                if (valueInternal is CellFormula)
                {
                    ((CellFormula) valueInternal).Value = value;
                }
                else
                {
                    this.ValueInternal = value;
                    base.CheckMultiline(value);
                }
            }
        }

        internal object ValueInternal
        {
            get
            {
                if (this.cellValue is MergedCellRange)
                {
                    return ((MergedCellRange) this.cellValue).ValueInternal;
                }
                return this.cellValue;
            }
            set
            {
                if (this.cellValue is MergedCellRange)
                {
                    ((MergedCellRange) this.cellValue).ValueInternal = value;
                }
                else
                {
                    this.cellValue = value;
                }
            }
        }
    }
}
